package com.itheima.java;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 加了这个注解后 这个类就成了服务器类 参数是监听的地址
 * 下面的几个方法类似于生命周期方法 当客户端来连接的时候 告诉服务器端应该来做什么事情
 */
@ServerEndpoint("/myWs")
@Component
@Slf4j
public class WsServerEndpoint {

    Map<String  , Session> sessionMap = new ConcurrentHashMap<>() ; //跟 HashMap 的区别是这个实现类是线程安全的

    /**
     * 当客户端来连接的时候执行的初始方法
     *      连接的时候会获取一个参数 Session
     */
    @OnOpen
    public void onOpen(Session session) {
        /**
         * Session要保存起来 因为可能不止一个客户端来连接 可以用 List
         * 但是这里用Map 每一个 Session 可以对应一个 key 方便查找
         */
        sessionMap.put(session.getId(),  session) ;
        log.info("客户端连接成功");
    }

    /**
     * 当客户端发送消息的时候触发
     */
    @OnMessage
    public String onMessage(String text) {
        log.info("客户端发送：" + text);

        return "已收到消息" ;
    }

    /**
     * 当客户端断开连接的时候触发
     */
    @OnClose
    public void onClose(Session session) {
        //从集合中移除掉这个连接
        sessionMap.remove(session.getId()) ;
        log.info("客户端断开连接");
    }

    /**
     * 每隔两秒给所有的客户端发送消息
     */
    @Scheduled(fixedRate = 2000 )
    public void sendMessage() throws IOException {
        for(String key : sessionMap.keySet()) {
            sessionMap.get(key).getBasicRemote().sendText("心跳") ;   // getBasicRemote() 获取远程

        }
    }
}
